﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Net;
using System.Net.Cache;
using System.Net.Http.Headers;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;
using Senparc.Weixin;
using Senparc.Weixin.MP;
using Senparc.Weixin.TenPay.V3;
using Senparc.Weixin.WxOpen.AdvancedAPIs.Sns;
using Senparc.Weixin.WxOpen.Containers;
using Senparc.Weixin.WxOpen.Entities;
using System.Text;
using System.Threading;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto.Parameters;




namespace SDWXServer
{
    public static class WXService
    {
        //与微信小程序账号后台的AppId设置保持一致，区分大小写。
        public static readonly string WxOpenAppId = Senparc.Weixin.Config.SenparcWeixinSetting.WxOpenAppId;
        //与微信小程序账号后台的AppId设置保持一致，区分大小写。
        public static readonly string WxOpenAppSecret = Senparc.Weixin.Config.SenparcWeixinSetting.WxOpenAppSecret;

        static WXService()
        {
        }
        public static JsCode2JsonResult Getjscode2session(string wxCode)
        {
            var jsonResult = SnsApi.JsCode2Json(WxOpenAppId, WxOpenAppSecret, wxCode);

            return jsonResult;
        }
        public static DecodedPhoneNumber DecryptPhoneNumber(string sessionKey, string encryptedData, string iv)
        {
            var data = Senparc.Weixin.WxOpen.Helpers.EncryptHelper.DecryptPhoneNumber(sessionKey, encryptedData, iv);

            return data;
        }
        public static DecodedUserInfo DecodeUserInfoBySessionId(string sessionKey, string encryptedData, string iv)
        {
            var data = Senparc.Weixin.WxOpen.Helpers.EncryptHelper.DecodeUserInfoBySessionId(sessionKey, encryptedData, iv);

            return data;
        }

        //public static void SendWRZSMPMessage_PaySuccess(string mpOpenId, string title, string totalFee, string time, string balance, string remark)
        //{
        //    var templateId = "G6qUCzag7V48plqHnn019Q4c9DO7tQKQ09W4qKEDw40";
        //    var url = "";
        //    var pagepath = "pages/index/index";
        //    SendWRZSMPMessage(mpOpenId, templateId, url, pagepath, title, totalFee, time, balance, "", "", remark);
        //}
        //public static void SendWRZSMPMessage_BalanceReminder(string mpOpenId, string title, string balance, string jifen, string cardNo, string remark)
        //{
        //    var templateId = "hwtnzN6IDS49uFoOEK0PoQR0SrIR0JJ1Ov4Q66bY5As";
        //    var url = "";
        //    var pagepath = "pages/index/index";
        //    SendWRZSMPMessage(mpOpenId, templateId, url, pagepath, title, balance, jifen, cardNo, "", "", remark);
        //}
        //public static void SendWRZSMPMessage_TransactionReminder(string mpOpenId, string title, string time, string type, string amount, string balance, string source, string remark)
        //{
        //    var templateId = "hwtnzN6IDS49uFoOEK0PoQR0SrIR0JJ1Ov4Q66bY5As";
        //    var url = "";
        //    var pagepath = "pages/index/index";
        //    SendWRZSMPMessage(mpOpenId, templateId, url, pagepath, title, time, type, amount, balance, source, remark);
        //}

        public static void SendWRZSMPMessage(string mpOpenId, string templateId, string url, string pagepath, string first, string keyword1, string keyword2, string keyword3, string keyword4, string keyword5, string remark)
        {
            try
            {
                var templateData = new Models.WRZSWeixinTemplateMsg(templateId, url);
                templateData.first = new Senparc.Weixin.MP.AdvancedAPIs.TemplateMessage.TemplateDataItem(first);
                templateData.keyword1 = new Senparc.Weixin.MP.AdvancedAPIs.TemplateMessage.TemplateDataItem(keyword1);
                templateData.keyword2 = new Senparc.Weixin.MP.AdvancedAPIs.TemplateMessage.TemplateDataItem(keyword2);
                templateData.keyword3 = new Senparc.Weixin.MP.AdvancedAPIs.TemplateMessage.TemplateDataItem(keyword3);
                templateData.keyword4 = new Senparc.Weixin.MP.AdvancedAPIs.TemplateMessage.TemplateDataItem(keyword4);
                templateData.keyword5 = new Senparc.Weixin.MP.AdvancedAPIs.TemplateMessage.TemplateDataItem(keyword5);
                templateData.remark = new Senparc.Weixin.MP.AdvancedAPIs.TemplateMessage.TemplateDataItem(remark);

                var miniProgram = new Senparc.Weixin.MP.AdvancedAPIs.TemplateMessage.TempleteModel_MiniProgram();
                miniProgram.appid = Senparc.Weixin.Config.SenparcWeixinSetting.WxOpenAppId;
                miniProgram.pagepath = pagepath;

                var appId = Senparc.Weixin.Config.SenparcWeixinSetting.WeixinAppId;
                var appSecret = Senparc.Weixin.Config.SenparcWeixinSetting.WeixinAppSecret;
                var accessToken = Senparc.Weixin.MP.Containers.AccessTokenContainer.TryGetAccessToken(appId, appSecret);
                var result = Senparc.Weixin.MP.AdvancedAPIs.TemplateApi.SendTemplateMessage(accessToken, mpOpenId, templateData, miniProgram);
            }
            catch (Exception e)
            {
                KD.Logger.Info("公众号模版消息发送", e);
            }
        }

        public static string GetWxaCodeUnlimit(string scene, string page, Int32 width)
        {
            var imageBase64 = "";

            var fileDir = System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "Images");
            if (System.IO.Directory.Exists(fileDir) == false) System.IO.Directory.CreateDirectory(fileDir);
            var filePath = Path.Combine(fileDir, string.Format("{0}.jpg", scene));
            if (System.IO.File.Exists(filePath)) System.IO.File.Delete(filePath);

            var accessToken = Senparc.Weixin.MP.Containers.AccessTokenContainer.TryGetAccessToken(WxOpenAppId, WxOpenAppSecret);
            var result = Senparc.Weixin.WxOpen.AdvancedAPIs.WxApp.WxAppApi.GetWxaCodeUnlimit(accessToken, filePath, scene, page, width, false, null, true, 10000);
            if (result.errcode == (ReturnCode)0)
            {
                if (System.IO.File.Exists(filePath))
                {
                    using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
                    {
                        using (var br = new BinaryReader(fs))
                        {
                            var image_Data = br.ReadBytes((Int32)fs.Length);
                            imageBase64 = Convert.ToBase64String(image_Data);
                        }
                    }
                }
            }
            else
            {
                throw new Exception(result.errmsg);
            }

            return imageBase64;
        }

    //    public static Newtonsoft.Json.Linq.JObject PayInfo(string userOpenID, Int32 totalFee, string body, string userHostAddress, string attach)
    //    {
    //        var resultPayInfo = new Newtonsoft.Json.Linq.JObject();
    //        if (string.IsNullOrWhiteSpace(body)) throw new Exception("body不能为空");

    //        var out_trade_no = string.Format("WxPay{0}{1}", DateTime.Now.ToString("yyyyMMddHHmmss"), TenPayV3Util.BuildRandomStr(6));
    //        resultPayInfo["out_trade_no"] = out_trade_no;

    //        var url = @"https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi";
    //        var rqdata = new Newtonsoft.Json.Linq.JObject();
    //        //rqdata["time_expire"] = DateTime.UtcNow.AddMinutes(30d).ToString();
    //        var amount = new Newtonsoft.Json.Linq.JObject();
    //        amount["total"] = totalFee;
    //        amount["currency"] = "CNY";
    //        rqdata["amount"] = amount;

    //        rqdata["mchid"] = TenPayV3Info.MchId;
    //        rqdata["description"] = body;
    //        rqdata["notify_url"] = TenPayV3Info.TenPayV3_WxOpenNotify;

    //        var payer = new Newtonsoft.Json.Linq.JObject();
    //        payer["openid"] = userOpenID;
    //        rqdata["payer"] = payer;

    //        rqdata["out_trade_no"] = out_trade_no;
    //        //rqdata["goods_tag"] = "WXG";
    //        rqdata["appid"] = TenPayV3Info.AppId;
    //        rqdata["attach"] = attach;

    //        var detail = new Newtonsoft.Json.Linq.JObject();
    //        //rqdata["detail"] = detail;

    //        var scene_info = new Newtonsoft.Json.Linq.JObject();
    //        //rqdata["scene_info"] = scene_info;

    //        var settle_info = new Newtonsoft.Json.Linq.JObject();
    //        settle_info["profit_sharing"] = false;
    //        //rqdata["settle_info"] = settle_info;

    //        var data = rqdata.ToString();
    //        KD.Logger.Info(string.Format("PayInfo-HttpPost:{0}", data));
    //        var resultStr = PostJson(url, data);
    //        KD.Logger.Info(string.Format("PayInfo-Received:{0}", resultStr));

    //        var resultData = Kingdee.BOS.JSON.JSONObject.Parse(resultStr, new Kingdee.BOS.JSON.JSONObject());
    //        var prepay_id = resultData.GetValue<string>("prepay_id", "");
    //        if (string.IsNullOrWhiteSpace(prepay_id))
    //        {
    //            throw new Exception(resultStr);
    //        }

    //        //获取微信时间格式
    //        var timeStamp = TenPayV3Util.GetTimestamp();
    //        //随机生成Noncestr
    //        var nonceStr = TenPayV3Util.GetNoncestr();
    //        var package = string.Format("prepay_id={0}", prepay_id);
    //        resultPayInfo["appId"] = TenPayV3Info.AppId;
    //        resultPayInfo["timeStamp"] = timeStamp;
    //        resultPayInfo["nonceStr"] = nonceStr;
    //        resultPayInfo["package"] = package;
    //        //签名
    //        var signSB = new StringBuilder();
    //        signSB.Append(TenPayV3Info.AppId).Append('\n');
    //        signSB.Append(timeStamp).Append('\n');
    //        signSB.Append(nonceStr).Append('\n');
    //        signSB.Append(package).Append('\n');
    //        resultPayInfo["paySign"] = Sign(signSB.ToString());

    //        return resultPayInfo;
    //}

    //    /// <summary>
    //    /// 支付查询
    //    /// </summary>
    //    /// <param name="tranId">微信订单号</param>
    //    /// <param name="outNos">商户订单号</param>
    //    /// <returns></returns>
    //    public static Newtonsoft.Json.Linq.JObject PayQuery(string tranId, string outNos)
    //    {
    //        var resultPayQuery = new Newtonsoft.Json.Linq.JObject();

    //        try
    //        {
    //            string norcestr = TenPayV3Util.GetNoncestr();
    //            var xmlDataInfo = new TenPayV3OrderQueryRequestData(TenPayV3Info.AppId, TenPayV3Info.MchId, tranId, norcestr, outNos, TenPayV3Info.Key);
    //            var resultOrderQuery = TenPayV3.OrderQuery(xmlDataInfo);
    //            resultPayQuery = Newtonsoft.Json.Linq.JObject.FromObject(resultOrderQuery);
    //        }
    //        catch (Exception e)
    //        {
    //            KD.Logger.Error("PayQuery", e);
    //        }

    //        return resultPayQuery;
    //    }

    //    private static TenPayV3Info _tenPayV3Info;
    //    public static TenPayV3Info TenPayV3Info
    //    {
    //        get
    //        {
    //            if (_tenPayV3Info == null)
    //            {
    //                _tenPayV3Info = new TenPayV3Info(Senparc.Weixin.Config.SenparcWeixinSetting);
    //                TenPayV3InfoCollection.Register(_tenPayV3Info, "SDWXServer");
    //            }
    //            return _tenPayV3Info;
    //        }
    //    }
    //    public static string PostJson(string url, string datajson)
    //    {
    //        var requestResult = "";

    //        var request = (HttpWebRequest)WebRequest.Create(url);
    //        request.Method = "POST";
    //        request.Timeout = 10000;
    //        request.ContentType = "application/json";
    //        request.Accept = "application/json,*/*";
    //        request.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727)";
    //        var noCachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.NoCacheNoStore);
    //        request.CachePolicy = noCachePolicy;

    //        var byteData = Encoding.UTF8.GetBytes(datajson);
    //        var length = byteData.Length;
    //        using (var writer = request.GetRequestStream())
    //        {
    //            writer.Write(byteData, 0, length);
    //            writer.Close();
    //        }
    //        SetHttpWebRequestAuthorization(request, datajson);

    //        using (var response = (HttpWebResponse)request.GetResponse())
    //        {
    //            using (var stream = response.GetResponseStream())
    //            {
    //                using (var reader = new StreamReader(stream, Encoding.UTF8))
    //                {
    //                    requestResult = reader.ReadToEnd();
    //                }
    //            }
    //            response.Close();
    //        }

    //        return requestResult;
    //    }
    //    static void SetHttpWebRequestAuthorization(HttpWebRequest request, string body)
    //    {
    //        var auth = BuildAuth(request, body);
    //        var value = $"WECHATPAY2-SHA256-RSA2048 {auth}";
    //        request.Headers.Add("Authorization", value);

    //        KD.Logger.Info(string.Format("Authorization:{0}", value));
    //    }
    //    static string BuildAuth(HttpWebRequest request, string body)
    //    {
    //        var auth = "";
    //        var method = request.Method.ToString();

    //        var uri = request.RequestUri.PathAndQuery;
    //        var timestamp = DateTimeOffset.Now.ToUnixTimeSeconds();
    //        var nonce = Path.GetRandomFileName();

    //        var message = $"{method}\n{uri}\n{timestamp}\n{nonce}\n{body}\n";
    //        var signature = Sign(message);
    //        auth = $"mchid=\"{TenPayV3Info.MchId}\",nonce_str=\"{nonce}\",timestamp=\"{timestamp}\",serial_no=\"{SerialNo}\",signature=\"{signature}\"";

    //        return auth;
    //    }
    //    /// <summary>
    //    /// 商户证书序列号
    //    /// </summary>
    //    static string SerialNo = "7CB2830747B0436DA9F562C0A54FE1F0ABA5A900";
    //    static string PrivateKey { get; set; }
    //    static string GetPrivateKey()
    //    {
    //        if (string.IsNullOrWhiteSpace(PrivateKey))
    //        {
    //            var pfx = "apiclient_key.pem";
    //            var pfxPassword = TenPayV3Info.MchId;
    //            var pfxFilePath = System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "Bin", pfx);
    //            if (File.Exists(pfxFilePath) == false) throw new Exception(string.Format("找不到签名证书{0}", pfx));
    //            var fileContent = "";
    //            using (var sr = new StreamReader(pfxFilePath))
    //            {
    //                fileContent = sr.ReadToEnd();
    //            }
    //            fileContent = fileContent.Replace("-----BEGIN PRIVATE KEY-----", "").Replace("-----END PRIVATE KEY-----", "").Trim('\n', '\r').Trim();
    //            PrivateKey = fileContent;

    //            KD.Logger.Info(string.Format("PrivateKey:{0}", PrivateKey));
    //        }

    //        return PrivateKey;
    //    }
    //    static string Sign(string message)
    //    {
    //        var privateData = "";
    //        // NOTE： 私钥不包括私钥文件起始的-----BEGIN PRIVATE KEY-----
    //        //        亦不包括结尾的-----END PRIVATE KEY-----
    //        byte[] keyData = Convert.FromBase64String(GetPrivateKey());
    //        using (CngKey cngKey = CngKey.Import(keyData, CngKeyBlobFormat.Pkcs8PrivateBlob))
    //        using (RSACng rsa = new RSACng(cngKey))
    //        {
    //            byte[] data = System.Text.Encoding.UTF8.GetBytes(message);
    //            privateData = Convert.ToBase64String(rsa.SignData(data, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1));
    //        }

    //        return privateData;
    //    }
    }
    //public static class AesGcm
    //{
    //    private static string ALGORITHM = "AES/GCM/NoPadding";
    //    private static int TAG_LENGTH_BIT = 128;
    //    private static int NONCE_LENGTH_BYTE = 12;
    //    public static string AES_KEY;

    //    public static string AesGcmDecrypt(string associatedData, string nonce, string ciphertext)
    //    {
    //        AES_KEY = WXService.TenPayV3Info.Key;
    //        GcmBlockCipher gcmBlockCipher = new GcmBlockCipher(new AesEngine());
    //        AeadParameters aeadParameters = new AeadParameters(
    //            new KeyParameter(Encoding.UTF8.GetBytes(AES_KEY)),
    //            128,
    //            Encoding.UTF8.GetBytes(nonce),
    //            Encoding.UTF8.GetBytes(associatedData));
    //        gcmBlockCipher.Init(false, aeadParameters);

    //        byte[] data = Convert.FromBase64String(ciphertext);
    //        byte[] plaintext = new byte[gcmBlockCipher.GetOutputSize(data.Length)];
    //        int length = gcmBlockCipher.ProcessBytes(data, 0, data.Length, plaintext, 0);
    //        gcmBlockCipher.DoFinal(plaintext, length);
    //        return Encoding.UTF8.GetString(plaintext);
    //    }
    //}
}